// axios 实例封装（含拦截器、类型）

import axios from 'axios';
import type {
  AxiosResponse,
  AxiosError,
  InternalAxiosRequestConfig,
} from 'axios';
import { message } from 'antd';

// 自定义响应数据结构
interface IResponse<T = unknown> {
  // 业务状态码
  code: number;
  // 实际业务数据 表示任意类型
  data: T;
  // 提示信息
  message: string;
  // 是否成功
  success: boolean;
}

// 扩展axios类型
// 扩展请求配置
type IRequestConfig = InternalAxiosRequestConfig & {
  // 是否显示axios
  showLoading?: boolean;
};

// 扩展响应数据类型
type IResponseData<T = unknown> = AxiosResponse<IResponse<T>>;

// 扩展错误类型（兼容axios错误）
type IAxiosError = AxiosError<{
  code: number;
  message: string;
}> & {
  response: IResponseData; //关联响应数据
};

// 创建axios实例
const service = axios.create({
  baseURL: import.meta.env.VITE_API_URL,
  // 超时时间10s
  timeout: 10000,
  // 跨域不携带cookie（登录接口通常不需要）
  withCredentials: false,
});

// 请求拦截器
service.interceptors.request.use(
  (config: IRequestConfig) => {
    // 携带token
    const token = localStorage.getItem('token');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error: IAxiosError) => {
    // 请求错误
    return Promise.reject(error);
  }
);

// 响应拦截器
service.interceptors.response.use(
  (response: IResponseData) => {
    const res = response.data;
    if (!res.success) {
      // 业务错误（404未登录、500服务器错误）
      message.error(res.message || '请求失败，请稍后重试');

      if (res.code === 401) {
        localStorage.removeItem('token');
        window.location.href = '/login';
      }
      return Promise.reject(new Error(res.message || '请求失败'));
    }
    // 成功时返回完整响应，让导出函数处理数据提取
    return response;
  },
  (error: IAxiosError) => {
    const msg =
      error.response?.data?.message ||
      error.message ||
      '网络异常，请检查网络连接';
    message.error(msg);
    //    抛出错误 阻止后续逻辑执行
    return Promise.reject(error);
  }
);

export const get = <T = any>(url: string, config?: IRequestConfig) => {
  return service.get<IResponse<T>>(url, config).then(response => response.data);
};

export const post = <T = any>(
  url: string,
  data?: any,
  config?: IRequestConfig
) => {
  return service
    .post<IResponse<T>>(url, data, config)
    .then(response => response.data);
};

export default service;
